package logger

import (
	"io"
	"os"
	"time"

	"github.com/spf13/viper"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

var sugar *zap.SugaredLogger

// SetupLogger function setup loggger
// func SetupLogger(writers []string, format string, level string,
//
//	fileName string, maxSize int, maxBackups int, maxAge int, compress bool) {
func SetupLogger(config *viper.Viper) {
	var cores []zapcore.Core
	var write io.Writer
	// 检查日志格式参数
	format := config.GetString("log.format")
	if format != "console" && format != "json" {
		panic("无效的日志格式：" + format)
	}
	encoder := getEncoder(format)
	writers := config.GetStringSlice("log.writers")
	for _, writer := range writers {
		if writer == "file" {
			write = &lumberjack.Logger{
				Filename:   config.GetString("log.fileName"), // 日志文件名
				MaxSize:    config.GetInt("log.maxSize"),     // 日志大小(MB)
				MaxBackups: config.GetInt("log.maxBackups"),  // 日志保留的文件数据量
				MaxAge:     config.GetInt("log.maxAge"),      // 日志保存天数
				Compress:   config.GetBool("log.compress"),   // 是否压缩
			}
		} else if writer == "console" {
			write = os.Stdout
		} else {
			panic("无效的日志写入器")
		}
		writerSyncer := zapcore.AddSync(write)
		core := zapcore.NewCore(encoder, writerSyncer, getLevel(config.GetString("log.level")))
		cores = append(cores, core)
	}
	logger := zap.New(zapcore.NewTee(cores...))
	sugar = logger.Sugar()
}

func getLevel(level string) zapcore.LevelEnabler {
	switch level {
	case "debug":
		return zapcore.DebugLevel
	case "info":
		return zapcore.InfoLevel
	case "warn":
		return zapcore.WarnLevel
	case "error":
		return zapcore.ErrorLevel
	case "dpanic":
		return zapcore.DPanicLevel
	case "panic":
		return zapcore.PanicLevel
	case "fatal":
		return zapcore.FatalLevel
	default:
		panic("无效的日志级别")
	}
}

// time format yyyy-mm-dd hh:MM:ss.000
func opmTimeLayout(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
}

// getEncoder function get a log encoder
func getEncoder(option string) zapcore.Encoder {
	encoderConfig := zap.NewProductionEncoderConfig()
	encoderConfig.EncodeTime = opmTimeLayout                // 日志时间格式
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // 日志级别使用大写字母
	if option == "json" {
		return zapcore.NewJSONEncoder(encoderConfig)
	} else if option == "console" {
		return zapcore.NewConsoleEncoder(encoderConfig)
	} else {
		panic("获取日志编码器失败:输入参数有误(json,console)")
	}
}

// SyncLogger function sync logger
func SyncLogger() {
	defer sugar.Sync()
}
